module ActsAsAspdotnet::ValidationHelpers
  
  
  module ValidationTagHelpers
  
    # wrap submit tag to call doPostBack
    def submit_tag(value = "Save changes", options = {})
      options = {:onclick => "__doPostBack();return false;"}.merge(options)    
      super(value, options)
    end
  
    # add a required field validator to the page
    def required_field_validator(object_name, method_name, error_message=nil, options={})
      required_field_validator_tag("#{object_name}_#{method_name}", error_message, options)
    end
    alias :required_field :required_field_validator
    
    def required_field_validator_tag(control_to_validate, error_message=nil, options={})    
      # prepopulate initialvalue
      options = {:initialvalue => ""}.merge(options)

      error_message ||= "is required."

      # <span controltovalidate="Password" errormessage="Password Required" id="RequiredFieldValidator2" evaluationfunction="RequiredFieldValidatorEvaluateIsValid" initialvalue="" style="color:Red;visibility:hidden;">Password Required</span>
      validator_control_tag(control_to_validate, error_message, "RequiredFieldValidatorEvaluateIsValid", options)
    end
    
    # regular expression validator
    def regular_expression_validator(object_name, method_name, regex, error_message=nil, options={})
      regular_expression_validator_tag("#{object_name}_#{method_name}", regex, error_message, options)
    end    
    def regular_expression_validator_tag(control_to_validate, regex, error_message=nil, options={})    
      options = {:validationexpression => regex}.merge(options)

      error_message ||= "has a bad format."

      # <span controltovalidate="UserName" errormessage="Invalid Email Format" id="RegularExpressionValidator1" evaluationfunction="RegularExpressionValidatorEvaluateIsValid" validationexpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" style="color:Red;visibility:hidden;">Invalid Email Format</span>
      validator_control_tag(control_to_validate, error_message, "RegularExpressionValidatorEvaluateIsValid", options)
    end
    
    # range validator
    def range_validator(object_name, method_name, min_value = 0, max_value = 100, error_message = nil,  options = {})
      range_validator_tag("#{object_name}_#{method_name}", min_value, max_value, error_message, options)
    end    
    def range_validator_tag(control_to_validate, min_value = 0, max_value = 100, error_message = nil,  options = {})
      options = {:type => "Integer", :minimumvalue => min_value, :maximumvalue => max_value}.merge(options)

      error_message ||= "is out of range [#{min_value}-#{max_value}]."

      # <span controltovalidate="PercentPaid" errormessage="RangeValidator" id="RangeValidator1" type="Integer" evaluationfunction="RangeValidatorEvaluateIsValid" maximumvalue="50" minimumvalue="20" style="color:Red;visibility:hidden;">RangeValidator</span>
      validator_control_tag(control_to_validate, error_message, "RangeValidatorEvaluateIsValid", options)
    end
    
    # compare validator
    def compare_validator(object_name, method_name, method_name2, error_message = nil,  options = {})
      compare_validator_tag("#{object_name}_#{method_name}", "#{object_name}_#{method_name2}", error_message, options)
    end    
    def compare_validator_tag(control_to_validate, control_to_validate2, error_message = nil,  options = {})
      control2_id = client_id(control_to_validate2)
      options = {:controlhookup => control2_id, :controltocompare => control2_id}.merge(options)

      error_message ||= "is does not match."
      
      # <span controltovalidate="Password2" errormessage="Passwords do not match" id="CompareValidator1" evaluationfunction="CompareValidatorEvaluateIsValid" controltocompare="Password" controlhookup="Password" style="color:Red;visibility:hidden;">Passwords do not match</span>
      validator_control_tag(control_to_validate, error_message, "CompareValidatorEvaluateIsValid", options)
    end
  
    # wrap the validator control
    def validator_control_tag(control_to_validate, error_message, eval_function, options={})
      control_id = client_id(control_to_validate)
      validator_id = control_id+"_#{eval_function}"
      @page_validators ||= []
      @page_validators << validator_id
      content_tag(:span, error_message, {:errormessage => error_message, :id => validator_id, :controltovalidate => control_id, :evaluationfunction => eval_function, :style => "color:Red;visibility:hidden;"}.merge(options))
    end
  
    # build page validators
    def page_validators
    
      # declare the validators on the page
      @page_validators ||= []
      page_validators_js = []
      @page_validators.each do |validator|
        page_validators_js << %(document.getElementById("#{validator}"))
      end
    
      [
      
      # clear the validators
      # Good thing Microsoft put the <!-- //--> around the script tag
      # this allows our page to be compatible with Netscape 1.0. Huw-rah!
      %(<script type="text/javascript">
        <!--
        var Page_Validators =  new Array(#{page_validators_js.join(",")});
        // -->
        </script>),

      # who knooooows what the fuck this thing does
      %(<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBQLogc3PAQKvruq2CALSxeCRDwLN9JqEDQLvz/Fl3FzALZGUbkm8ADXWd3gnH8rTjfo=" />),

      # initialize all our validators by cycling through them
      %(<script type="text/javascript">
        <!--
        var Page_ValidationActive = false;
        if (typeof(ValidatorOnLoad) == "function") {
            ValidatorOnLoad();
        }

        function ValidatorOnSubmit() {
            if (Page_ValidationActive) {
                return ValidatorCommonOnSubmit();
            }
            else {
                return true;
            }
        }
        // -->
        </script>
        )].join("\n")
    end
  
  
  
    # enable doPostBack and link buttons
    def do_post_back(html_options)
      logger.debug "HTML OPTIONS"
      logger.debug html_options.inspect
      "
        <script type=\"text/javascript\">
        <!--
        var theForm = document.forms['#{html_options["id"]}'];
        if (!theForm) {
            theForm = document.#{html_options["id"]};
        }
        function __doPostBack(eventTarget, eventArgument) {
          var isValid = true;
          if (typeof(Page_ClientValidate) == 'function'){
            isValid = Page_ClientValidate();
          }
        
          if(isValid)
          {
            if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
                theForm.__EVENTTARGET.value = eventTarget;
                theForm.__EVENTARGUMENT.value = eventArgument;
                theForm.submit();
            }          
          }
        }
        // -->
        </script>
      "
    end
  end
  
  # build some wrappers so we can add it to FormBuilder
  module FormBuilderValidationHelpers
    def required_field_validator(method_name, error_message = nil, options = {})
      @template.required_field_validator(@object_name, method_name, error_message, options)
    end
    alias :required_field :required_field_validator

    def regular_expression_validator(method_name, regex, error_message = nil, options = {})
      @template.regular_expression_validator(@object_name, method_name, regex, error_message, options)
    end
    
    def range_validator(method_name, min_value = 0, max_value = 100, error_message = nil,  options = {})
      @template.range_validator(@object_name, method_name, min_value, max_value, error_message, options)
    end
    
    def compare_validator(method_name, method_name2, error_message = nil,  options = {})
      @template.compare_validator(@object_name, method_name, method_name2, error_message, options)
    end
    
    
  end
  
end